package com.zzyl.intercept;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.json.JSONUtil;
import com.zzyl.enums.BasicEnum;
import com.zzyl.exception.BaseException;
import com.zzyl.properties.JwtTokenManagerProperties;
import com.zzyl.utils.JwtUtil;
import com.zzyl.utils.UserThreadLocal;
import com.zzyl.vo.UserVo;
import io.jsonwebtoken.Claims;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
import java.util.Map;

@Slf4j
@Component
public class AdminInterceptor implements HandlerInterceptor {
    @Autowired
    private JwtTokenManagerProperties jwtTokenManagerProp;
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //获取请求路径
        String uri = request.getRequestURI();
        //获取请求方式
        String method = request.getMethod();
        //拼接为请求url
        String targetUrl = method + uri;
        //判断是否登录路径
        if ("/security/login".equals(uri)){
            log.info("登录路径");
            //放行
            return true;
        }
        //获取请求头
        String token = request.getHeader("Authorization");
        if(StringUtils.isBlank(token)){
            log.info("token为空");
            throw new BaseException(BasicEnum.LOGIN_LOSE_EFFICACY);
        }
        try {
            //解析token
            Map<String, Object> claims = JwtUtil.parseJWT(jwtTokenManagerProp.getBase64EncodedSecretKey(), token);
            Object obj = claims.get("currentUser");
            UserVo userVo = JSONUtil.toBean(obj.toString(), UserVo.class);
            log.info("登录的用户id:{},{}",userVo.getId(),uri);
            //创建匹配对象
            AntPathMatcher matcher = new AntPathMatcher();
            //获取所有的按钮路径
            String butAllUrls = redisTemplate.opsForValue().get("resource:allurls");
            //转成集合
            List<String> stringList = JSONUtil.toList(butAllUrls, String.class);
            if (CollectionUtil.isEmpty(stringList)){
                log.error("按钮路径为空");
                throw new BaseException(BasicEnum.LOGIN_LOSE_EFFICACY);
            }
            //用于标记路径 false -> 其他路径 true -> 按钮路径
            boolean flag = false;
            //循环遍历所有按钮路径
            for (String butUrl : stringList) {
                //判断请求路径是否为按钮路径
                if (matcher.match(butUrl,targetUrl)){
                    //是按钮路径
                    flag = true;
                    break;
                }
            }
            //判断请求路径
            if (!flag){
                //不为按钮路径
                log.info("当前访问路径:{}",targetUrl);
                //放入ThreadLocal
                UserThreadLocal.setSubject(JSONUtil.toJsonStr(obj));
                return true;
            }else {
                //获取redis中的按钮路径
                String urls = redisTemplate.opsForValue().get("user:access:urls:"+userVo.getId());
                //转化为urls集合
                List<String> list = JSONUtil.toList(urls, String.class);
                //判断集合是否为空
                if (CollectionUtil.isEmpty(list)){
                    //集合为空
                    log.error("按钮路径为空");
                    throw new BaseException(BasicEnum.SECURITY_ACCESSDENIED_FAIL);
                }
                for (String url : list) {
                    //匹配路径
                    if (matcher.match(url,targetUrl)){
                        log.info("当前用户访问的路径:{}",url);
                        //放入ThreadLocal
                        UserThreadLocal.setSubject(JSONUtil.toJsonStr(obj));
                        return true;
                    }
                }
                //集合为空
                log.error("按钮路径为空");
                throw new BaseException(BasicEnum.SECURITY_ACCESSDENIED_FAIL);
            }
        }catch (Exception e){
            log.info("token解析失败");
            throw new BaseException(BasicEnum.LOGIN_LOSE_EFFICACY);
        }
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        //清除
        UserThreadLocal.removeSubject();
    }
}
